/*
 * Copyright 2009 Eat Local Food, LLC
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elf.gwt.common.client.access;

import java.util.Date;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONException;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;


/**
 * Class that acts as a client to a JSON service. 
 */

public class JSONServerAccess
{
	public final static String DEFAULT_REQUEST_URL = "php/action_component.php";

	private List<RequestParameter> requestParameterList;
	private JSONServerAccessCallback callback;
	protected Date dateLaunch;

	/**
	 * Constructors
	 */
	public JSONServerAccess()
	{
		this.requestParameterList = null;
		this.callback = null;
	}

	public JSONServerAccess(JSONServerAccessCallback callback, boolean secure)
	{
		this.requestParameterList = null;
		this.callback = callback;
	}

	public void setCallback(JSONServerAccessCallback callback) {
		this.callback = callback;
	}

	/**
	 * This is the request method
	 */

	public void doServerAccess(List<RequestParameter> requestParameterList)
	{
		setRequestParameterList(requestParameterList);
		try {
			String url = GWT.getHostPageBaseURL() + DEFAULT_REQUEST_URL;
			String request = getRequestString(getRequestParameterList());
			GWT.log(url + "?" + request, null);
			RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.POST, url);
			requestBuilder.setHeader("Content-Type", "application/x-www-form-urlencoded");
			dateLaunch = new Date();
			requestBuilder.sendRequest(request, new JSONDataAccessHandler());
		} catch (RequestException ex) {
			getCallback().onError(getRequestParameterList(), ex);
		}
	}

	/**
	 * This handles the response
	 * 
	 */
	protected class JSONDataAccessHandler implements RequestCallback 
	{
		public void onError(Request request, Throwable exception) {
			GWT.log("error", exception);
			getCallback().onError(getRequestParameterList(), exception);
		}

		public void onResponseReceived(Request request, Response response) {
			//Date datenow = new Date();
			//RootPanel.get().add(new InlineHTML("json = " + (datenow.getTime() - dateLaunch.getTime()) / 1000.0 + "<br/>"));
			String responseText = response.getText();

			if (responseText == null || responseText.trim().length() == 0)
			{
				Exception e = new Exception("No response for " + getRequestString(getRequestParameterList()));
				getCallback().onError(getRequestParameterList(), e);
			}
			else
			{
				int index = responseText.indexOf("{");
				if (index > 0)
				{
					String logResponse = responseText.substring(0, index).trim();
					if (logResponse.length() > 0) GWT.log(logResponse, null);
					responseText = responseText.substring(index);
				}

				if (index < 0)
				{
					Exception e = new Exception("Error on Server: " + responseText);
					getCallback().onError(getRequestParameterList(), e);
				}
				else
				{
					try {
						JSONValue jsonValue = JSONParser.parseLenient(responseText);
						getCallback().onResponseReceived(getRequestParameterList(), jsonValue);
					} catch (JSONException e) {
						getCallback().onError(getRequestParameterList(), e);
					}
				}
			}
		}
	}

	protected JSONServerAccessCallback getCallback() {
		return callback;
	}

	protected List<RequestParameter> getRequestParameterList() {
		return requestParameterList;
	}

	protected void setRequestParameterList(List<RequestParameter> requestParameterList) {
		this.requestParameterList = requestParameterList;
	}

	/**
	 * Converts the list of RequestParameters into a request string.
	 * @param requestParameterList
	 * @return
	 */
	protected String getRequestString(List<RequestParameter> requestParameterList)
	{
		String str = "";
		Iterator<RequestParameter> iter = requestParameterList.iterator();
		int i = 0;
		while (iter.hasNext())
		{
			RequestParameter rp = iter.next();
			if (i == 0) str += "";
			else str += "&";
			str += rp.getKey() + "=" + rp.getValue();
			i++;
		}

		return str;
	}
}
